﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.IO;
using System.Windows.Forms;
using System.Text.RegularExpressions;
using System.Collections;

namespace DbView
{

	public partial class TemplateEditForm : Form, ITemplateEditForm
	{
		Template editItem = null;

		////////////////////////////////////////////////////////////////////
		// Interface ITemplateEditForm
		public TemplateEditForm()
		{
			InitializeComponent();
		}

		public Template EditItem
		{
			get { return this.editItem; }
			set { this.editItem = value; }
		}

		public bool ShowForm() { return (this.ShowDialog() == DialogResult.OK) ? true : false; }

		////////////////////////////////////////////////////////////////////
		// Form stuff from here
		////////////////////////////////////////////////////////////////////
		private void btnOk_Click(object sender, EventArgs e)
		{
			this.ControlsToTemplate();
			if (ValidatesOk())
			{
				this.DialogResult = DialogResult.OK;
				this.Close();
			}
		}

		bool ValidatesOk()
		{
			string errMsg = "";
			if (this.editItem.Title.Trim().Length == 0)
				errMsg = "Please give the template a title";
			if (this.editItem.Code.Replace("\n", "").Trim().Length == 0)
				errMsg = "Please add template code before saving";
			if (errMsg.Length == 0)
				return true;
			MessageBox.Show(errMsg, "Cannot save yet", MessageBoxButtons.OK, MessageBoxIcon.Warning);
			return false;
		}

		private void btnCancel_Click(object sender, EventArgs e)
		{
			this.DialogResult = DialogResult.Cancel;
			this.Close();
		}

		private void TemplateToControls()
		{
			Template tmpl = this.editItem;
			this.textTitle.Text = tmpl.Title;
			this.textKeywords.Text = tmpl.Keywords;
			this.textCode.Text = tmpl.Code;
		}

		private void ControlsToTemplate()
		{
			Template tmpl = this.editItem;
			tmpl.Title = this.textTitle.Text;
			tmpl.Keywords = this.textKeywords.Text;
			tmpl.Code = this.textCode.Text;
		}

		private void TemplateEditForm_Load(object sender, EventArgs e)
		{
			//
			TemplateToControls();
		}

		private void btnCopy_Click(object sender, EventArgs e)
		{
			this.textCode.SelectAll();
			this.textCode.Copy();
			this.Close();
		}

	}

	public class Template
	{
		/*
			Class representing a sql snippet.
		*/
		public Template(String title)
		{
			this.Title = title;
			this.Keywords = "";
			this.Code = "";
		}
		public string Title { get { return this.title; } set { this.title = value; } }
		public string Keywords { get { return this.keyWords; } set { this.keyWords = value; } }
		public string Code { get { return this.code; } set { this.code = value; } }

		public bool Matches(String seek)
		{
			if (this.Title.ToUpper().IndexOf(seek.ToUpper()) != -1) return true;
			if (this.Keywords.ToUpper().IndexOf(seek.ToUpper()) != -1) return true;
			if (this.Code.ToUpper().IndexOf(seek.ToUpper()) != -1) return true;
			return false;
		}

		string title;
		string keyWords;
		string code;

		public override string ToString()
		{
			string rec = string.Format("Title:{0}\n", this.Title.Trim());
			rec += string.Format("Keywords:{0}\n", this.Keywords.Trim());
			// todo: trim off trailing \n from code
			this.TrimCode();
			rec += string.Format("Code:{0}\n...\n", this.Code);
			return rec;
		}

		void TrimCode()
		{
			while (this.code.Length > 0 && this.code[this.code.Length - 1] == '\n')
				this.code = this.code.Substring(0, this.code.Length - 1);
			this.code += "\n"; // just the one
		}
	}
	/*
		Note: slight confusion in teminology. Are these code samples
		or code templates? Until its resolved it means the same.
	*/
	public class TemplateCollection : IEnumerable
	{
		// hold Sample collection
		List<Template> m_Samples;

		public TemplateCollection()
		{
			this.m_Samples = new List<Template>();
		}

		public IEnumerator GetEnumerator()
		{
			foreach (Template tmpl in this.m_Samples)
			{
				yield return tmpl;
			}
		}

		public Template this[String title]
		{
			get
			{
				foreach (Template t in this)
				{
					if (t.Title == title) return t;
				}
				return null;
			}
		}

		public Template NewTemplate()
		{
			Template t = new Template("New");
			this.m_Samples.Add(t);
			return t;
		}

		public bool Remove(Template t)
		{
			return this.m_Samples.Remove(t);
		}

		public void LoadFile(String fileName)
		{
			this.m_Samples.Clear();
			if (!File.Exists(fileName))
			{
				string msg = string.Format("{0} does not exist!", fileName);
				Console.WriteLine(msg);
				StreamWriter sw = File.CreateText(fileName);
				sw.Close();
				//throw new Exception(msg);
			}
			StreamReader sr = File.OpenText(fileName);
			string input, data;
			Template tmpl = null;
			// parse input
			while ((input = sr.ReadLine()) != null)
			{
				int type = this.LineType(input, out data);
				switch (type)
				{
					case 1:
						tmpl = new Template(data);
						this.m_Samples.Add(tmpl);
						break;
					case 2:
						if (tmpl != null)
							tmpl.Keywords = data;
						break;
					case 3:
						if (tmpl != null)
							tmpl.Code = data;
						break;
					case 4:
						tmpl = null;
						break;
					case 0:
						if (tmpl != null)
							tmpl.Code += "\n" + data;
						break;
				}
			}
			sr.Close();
			// add one or you are stuck
			if (this.m_Samples.Count == 0)
			{
				tmpl = new Template("Show SQL version");
				this.m_Samples.Add(tmpl);
				tmpl.Keywords = "Version";
				tmpl.Code = "select @@VERSION";
			}
		}

		public void SaveFile(String fileName)
		{
			// make this a new file
			StreamWriter sw = File.CreateText(fileName);
			foreach (Template tmpl in this.m_Samples)
			{
				sw.WriteLine(tmpl.ToString());
			}
			sw.Close();
		}

		public DataTable MakeTable()
		{
			DataTable table = DataTableHelpers.MakeDataTable("Templates", "Title|Keywords|Template", "SSS");
			foreach (Template tmpl in this)
			{
				table.Rows.Add(new object[] { tmpl.Title, tmpl.Keywords, tmpl.Code });
			}
			return table;
		}


		private int LineType(String line, out string rest)
		{
			rest = line;
			if (rest.Trim() == "...")
				return -1;
			// regex string for a match pattern
			string regexString = @"^\s*(Title|Keywords|Code):(.*?)$";
			// regex object contrstucet with pattern
			Regex r = new Regex(regexString, RegexOptions.IgnoreCase);
			// string to compare
			Match m = r.Match(line);
			// if match
			if (m.Success)
			{
				string kw = m.Groups[1].Value;
				rest = m.Groups[2].Value;
				if (kw.ToUpper() == "TITLE")
					return 1;
				if (kw.ToUpper() == "KEYWORDS")
					return 2;
				if (kw.ToUpper() == "CODE")
					return 3;
			}
			return 0;
		}


	}
}
